package com.ruoyi.cs.service.impl;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.Response;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ExceptionUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.cs.domain.*;
import com.ruoyi.cs.domain.apiVo.TWarDto;
import com.ruoyi.cs.domain.apiVo.TWarGrateDto;
import com.ruoyi.cs.domain.vo.TWarResultVo;
import com.ruoyi.cs.mapper.*;
import com.ruoyi.cs.service.ITWarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 战令Service业务层处理
 * 
 * @author ruoyi
 * @date 2023-12-11
 */
@Service
@SuppressWarnings("all")
public class TWarServiceImpl implements ITWarService
{
    @Value("${ruoyi.icon-pic}")
    private String iconUrl;

    @Autowired
    private TWarMapper tWarMapper;
    @Autowired
    private TWarGrateMapper tWarGrateMapper;
    @Autowired
    private TBoxMapper tBoxMapper;
    @Autowired
    private TWarUserMapper tWarUserMapper;
    @Autowired
    private TWarReceiveMapper tWarReceiveMapper;
    @Autowired
    private TUserMapper tUserMapper;
    @Autowired
    private TBalanceChangeMapper tBalanceChangeMapper;
    @Autowired
    private TRechargeMapper tRechargeMapper;

    /**
     * 查询战令
     * 
     * @param id 战令主键
     * @return 战令
     */
    @Override
    public TWar selectTWarById(Long id)
    {
        return tWarMapper.selectTWarById(id);
    }

    /**
     * 查询战令列表
     * 
     * @param tWar 战令
     * @return 战令
     */
    @Override
    public List<TWar> selectTWarList(TWar tWar)
    {
        List<TWar> list = tWarMapper.selectTWarList(tWar);
        if(CollectionUtil.isNotEmpty(list)){
            /**设置最大等级*/
            List<String> ids = list.stream().map(TWar::getObjectId).collect(Collectors.toList());
            List<TWarResultVo> grateResultVos = tWarGrateMapper.maxGrateGroupWarId(ids);
            list.forEach(bean -> {
                Optional<Integer> optional = grateResultVos.stream().filter(vo -> vo.getWarId().equals(bean.getObjectId())).map(TWarResultVo::getMaxGrate).findFirst();
                if(optional.isPresent()){
                    bean.setMaxGrate(optional.get());
                }else {
                    bean.setMaxGrate(0);
                }
            });
            /**统计参与人数*/
            List<TWarResultVo> userResultVos = tWarUserMapper.countWarUserList(ids);
            list.forEach(bean -> {
                Optional<Long> optional = userResultVos.stream().filter(vo -> vo.getWarId().equals(bean.getObjectId())).map(TWarResultVo::getJoinUserNumber).findFirst();
                if(optional.isPresent()){
                    bean.setJoinUserNumber(optional.get());
                }else {
                    bean.setJoinUserNumber(0L);
                }
            });
        }
        return tWarMapper.selectTWarList(tWar);
    }

    /**
     * 新增战令
     * 
     * @param tWar 战令
     * @return 结果
     */
    @Override
    public int insertTWar(TWar tWar)
    {
        tWar.setCreateTime(DateUtils.getNowDate());
        tWar.setWarStatus(0);
        tWar.setObjectId(IdUtil.fastSimpleUUID());
        return tWarMapper.insertTWar(tWar);
    }

    /**
     * 修改战令
     * 
     * @param tWar 战令
     * @return 结果
     */
    @Override
    @Transactional
    public int updateTWar(TWar tWar)
    {
        tWar.setUpdateTime(DateUtils.getNowDate());
        if(Objects.nonNull(tWar.getWeeklyLimitObj())){
            tWar.setWeeklyLimit(tWar.getWeeklyLimitObj().toJSONString());
        }
        if(tWar.getWarStatus() == 1){/**上线，保证同一时间只有一个战令上线*/
            tWarMapper.updateTWarStatus();
        }
        if(tWar.getWarStatus() != 0){
            tWar.setCloseTime(null);
        }
        return tWarMapper.updateTWar(tWar);
    }

    /**
     * 批量删除战令
     * 
     * @param ids 需要删除的战令主键
     * @return 结果
     */
    @Override
    public int deleteTWarByIds(Long[] ids)
    {
        return tWarMapper.deleteTWarByIds(ids);
    }

    /**
     * 删除战令信息
     * 
     * @param id 战令主键
     * @return 结果
     */
    @Override
    public int deleteTWarById(Long id)
    {
        return tWarMapper.deleteTWarById(id);
    }

    /**
     * @Desc: 获取战令详细信息
     * @author: zz
     * @date: 2023/12/12
     */
    @Override
    public TWarDto getInfo(String userId) {
        /**获取最新战令*/
        TWar tWar = tWarMapper.lastWar();
        if(tWar == null){
            return new TWarDto();
        }
        TWarDto tWarDto = BeanUtil.copyProperties(tWar,TWarDto.class);
        /**获取战令等级*/
        TWarGrate tWarGrate = new TWarGrate();
        tWarGrate.setWarId(tWarDto.getObjectId());
        List<TWarGrate> tWarGrates = tWarGrateMapper.selectTWarGrateList(tWarGrate);
        List<TWarGrateDto> grateDtos  = BeanUtil.copyToList(tWarGrates,TWarGrateDto.class);
        if(CollectionUtil.isNotEmpty(grateDtos)){
            /**设置奖励内容*/
            List<String> boxIds = grateDtos.stream().filter(bean -> bean.getWarType() == 1).map(TWarGrateDto::getWarBox).distinct().map(String::valueOf).collect(Collectors.toList());
            List<TBox> tBoxList = tBoxMapper.getTBoxListBatch(null,boxIds);
            grateDtos.forEach(bean -> {
                if(bean.getWarType() == 0){
                    bean.setRewardName(bean.getWarFee()+"金币");
                    bean.setRewardPic(iconUrl);
                }else if(bean.getWarType() == 1){
                    Optional<TBox> optionalTBox = tBoxList.stream().filter(box -> box.getBoxId().equals(bean.getWarBox().toString())).findFirst();
                    if(optionalTBox.isPresent()){
                        bean.setRewardName(optionalTBox.get().getBoxName());
                        bean.setRewardPic(optionalTBox.get().getBoxPic());
                    }
                }
            });
        }
        /**当前用户等级*/
        if(StringUtils.isEmpty(userId)){
            tWarDto.setCurryUserGrate(0);
            tWarDto.setCurryUserExpe(grateDtos.get(0).getUpThreshold());
            /**未登录是都显示为待领取*/
            grateDtos.forEach(bean -> { bean.setReceiveStatus(0); });
        }else {
            /**获取当前用户等级*/
            TWarUser tWarUser = tWarUserMapper.getWarUser(tWarDto.getObjectId(),userId);
            if(tWarUser == null){
                tWarDto.setCurryUserGrate(0);
                tWarDto.setCurryUserExpe(BigDecimal.ZERO);
            }else {
                tWarDto.setCurryUserGrate(tWarUser.getWarGrate());
                tWarDto.setCurryUserExpe(tWarUser.getDraftValue());
            }
            /**获取当前等级上限*/
            TWarGrate lastGrate = this.getNextLevelAbove(tWarGrates,tWarDto.getCurryUserGrate());
            tWarDto.setCurryGrateUpLimit(lastGrate.getUpThreshold());

            /**设置用户的领取状态*/
            TWarReceive tWarReceive = new TWarReceive();
            tWarReceive.setWarId(tWarDto.getObjectId());
            tWarReceive.setUserId(userId);
            List<TWarReceive> tWarReceiveList = tWarReceiveMapper.selectTWarReceiveList(tWarReceive);
            grateDtos.forEach(bean -> {
                Optional<TWarReceive> optional = tWarReceiveList.stream().filter(rec -> rec.getWarGrate() == bean.getGrate()).findFirst();
                if(optional.isPresent()){
                    bean.setReceiveStatus(1);
                }else {
                    if(tWarUser != null && tWarUser.getWarGrate() >= bean.getGrate()){
                        bean.setReceiveStatus(0);
                    }else {
                        bean.setReceiveStatus(2);
                    }
                }
            });
        }
        tWarDto.setList(grateDtos);
        return tWarDto;
    }

    public TWarGrate getNextLevelAbove(List<TWarGrate> tWarGrates, int specifiedLevel) {
        TWarGrate maxLevelGrate = tWarGrates.get(tWarGrates.size() - 1); // 获取最大等级的 TWarGrate
        if (specifiedLevel >= maxLevelGrate.getGrate()) {
            return maxLevelGrate; // 如果指定等级大于等于最大等级，则直接返回最大等级的 TWarGrate
        }

        return tWarGrates.stream()
                .filter(grate -> grate.getGrate() > specifiedLevel) // 过滤出大于指定等级的等级
                .findFirst() // 找到第一个大于指定等级的等级
                .orElse(null); // 或者根据你的需求返回合适的值
    }

    /**
     * @Desc: 单个战令奖励领取
     * @author: zz
     * @date: 2023/12/13
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response singleReceive(String warId, Integer grate,String userId) throws Exception {
        /**根据用户ID获取用户信息*/
        TUser tUser = tUserMapper.selectTUserById(userId);
        if (tUser == null || !Constants.SUCCESS.equals(tUser.getDelFlag())) {
            return Response.fail(Constants.FAILCODE, "用户不存在或已被冻结，请联系管理员！");
        }
        /**战令*/
        TWar tWar = tWarMapper.selectTWarByObjectId(warId);
        if(tWar == null){
            return Response.fail("战令不存在！");
        }
        if(!tWar.getDelFlag().equals("0")){
            return Response.fail("战令已不存在！");
        }
        if(tWar.getWarStatus() != 1){
            return Response.fail("战令已结束！");
        }
        if(tWar.getBeginTime().getTime() > DateUtils.getNowDate().getTime()){
            return Response.fail("战令未开放！");
        }
        if(tWar.getCloseTime().getTime() < DateUtils.getNowDate().getTime()){
            return Response.fail("战令已结束！");
        }

        TWarGrate tWarGrate = tWarGrateMapper.getTWarReceiveById(warId,grate);
        if(tWarGrate == null){
            return Response.fail("战令等级不存在！");
        }
        /**获取用户等级*/
        TWarUser tWarUser = tWarUserMapper.getWarUser(warId,userId);
        if(tWarUser == null || tWarUser.getWarGrate() < grate){
            return Response.fail("不符合领取条件！");
        }

        TWarReceive tWarReceive = new TWarReceive();
        tWarReceive.setWarId(warId);
        tWarReceive.setUserId(userId);
        List<TWarReceive> tWarReceiveList = tWarReceiveMapper.selectTWarReceiveList(tWarReceive);
        long recnum = tWarReceiveList.stream().filter(bean -> bean.getWarGrate() == grate).count();
        if(recnum>0){
            return Response.fail("已领取过该战令等级奖励，请勿重复领取！");
        }

        BigDecimal addBalance = BigDecimal.ZERO;
        /**符合领取条件*/
        TWarReceive receive = new TWarReceive();
        receive.setUserId(userId);
        receive.setWarId(warId);
        receive.setWarGrateId(tWarGrate.getId());
        receive.setWarGrate(tWarGrate.getGrate());
        receive.setDraftValue(tWarUser.getDraftValue());
        receive.setCreateTime(DateUtils.getNowDate());
        receive.setWarType(tWarGrate.getWarType());
        if(tWarGrate.getWarType() == 0){
            receive.setWarFee(tWarGrate.getWarFee());
            receive.setUseStatus(1);
            addBalance = addBalance.add(tWarGrate.getWarFee());
        }else {
            receive.setWarBox(tWarGrate.getWarBox());
            receive.setUseStatus(0);
        }
        tWarReceiveMapper.insertTWarReceive(receive);

        /**领取金币*/
        if(addBalance.compareTo(BigDecimal.ZERO) > 0){
            BigDecimal beforeBalance = tUser.getUserBalance();
            tUser.setUserBalance(beforeBalance.add(addBalance));
            tUser.setUpdateTime(DateUtils.getNowDate());
            int row1 = tUserMapper.updateTUserBalance(tUser);
            if(row1 == 0){
                throw new SQLException("网络延迟,请重新抽奖! ");
            }

            /**余额变更记录表*/
            TBalanceChange balanceChange = new TBalanceChange();
            balanceChange.setUserId(userId);
            balanceChange.setBalanceBefore(beforeBalance);
            balanceChange.setBalanceAfter(tUser.getUserBalance());
            balanceChange.setOperationType(Constants.OPERATIONTYPE17);
            balanceChange.setFrequency(1);
            balanceChange.setFee(addBalance);
            balanceChange.setCorrespondingid(warId);
            balanceChange.setCreateTime(DateUtils.getNowDate());
            balanceChange.setSecondCurrencyBefore(tUser.getSecondCurrency());
            balanceChange.setSecondCurrencyAfter(tUser.getSecondCurrency());
            tBalanceChangeMapper.insertTBalanceChange(balanceChange);
        }
        return Response.success("领取成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response receive(String warId, String userId) throws Exception {
        /**根据用户ID获取用户信息*/
        TUser tUser = tUserMapper.selectTUserById(userId);
        if (tUser == null || !Constants.SUCCESS.equals(tUser.getDelFlag())) {
            return Response.fail(Constants.FAILCODE, "用户不存在或已被冻结，请联系管理员！");
        }
        /**战令*/
        TWar tWar = tWarMapper.selectTWarByObjectId(warId);
        if(tWar == null){
            return Response.fail("战令不存在！");
        }
        if(!tWar.getDelFlag().equals("0")){
            return Response.fail("战令已不存在！");
        }
        if(tWar.getWarStatus() != 1){
            return Response.fail("战令已结束！");
        }
        if(tWar.getBeginTime().getTime() > DateUtils.getNowDate().getTime()){
            return Response.fail("战令未开放！");
        }
        if(tWar.getCloseTime().getTime() < DateUtils.getNowDate().getTime()){
            return Response.fail("战令已结束！");
        }
        /**获取用户等级*/
        TWarUser tWarUser = tWarUserMapper.getWarUser(warId,userId);
        if(tWarUser == null){
            return Response.fail("不符合领取条件！");
        }

        TWarGrate paramGrate = new TWarGrate();
        paramGrate.setWarId(warId);
        List<TWarGrate> tWarGrateList = tWarGrateMapper.selectTWarGrateList(paramGrate);
        /**刷选出符合领取的等级*/
        List<TWarGrate> grateFilterList = tWarGrateList.stream().filter(bean -> bean.getGrate()<=tWarUser.getWarGrate()).collect(Collectors.toList());
        if(CollectionUtil.isEmpty(grateFilterList)){
            return Response.fail("没有可领取的战令奖励！");
        }

        TWarReceive tWarReceive = new TWarReceive();
        tWarReceive.setWarId(warId);
        tWarReceive.setUserId(userId);
        List<TWarReceive> tWarReceiveList = tWarReceiveMapper.selectTWarReceiveList(tWarReceive);
        /**可领取的战令奖励*/
        List<TWarGrate> grateArrayList = new ArrayList<>();
        grateFilterList.forEach(tWarGrate1 ->{
            long count = tWarReceiveList.stream().filter(bean -> tWarGrate1.getGrate() == bean.getWarGrate()).count();
            if(count == 0){
                grateArrayList.add(tWarGrate1);
            }
        });
        if(CollectionUtil.isEmpty(grateArrayList)){
            return Response.fail("没有可领取的战令奖励！");
        }

        /**插入领取记录*/
        List<TWarReceive> resultList = new ArrayList<>();
        grateArrayList.forEach(warGrate -> {
            TWarReceive receive = new TWarReceive();
            receive.setUserId(userId);
            receive.setWarId(warId);
            receive.setWarGrateId(warGrate.getId());
            receive.setWarGrate(warGrate.getGrate());
            receive.setDraftValue(tWarUser.getDraftValue());
            receive.setCreateTime(DateUtils.getNowDate());
            receive.setWarType(warGrate.getWarType());
            if(warGrate.getWarType() == 0){
                receive.setWarFee(warGrate.getWarFee());
                receive.setUseStatus(1);
            }else {
                receive.setWarBox(warGrate.getWarBox());
                receive.setUseStatus(0);
            }
            resultList.add(receive) ;
        });
        tWarReceiveMapper.batchInsertWarReceive(resultList);

        BigDecimal addBalance = resultList.stream().filter(warGrate -> warGrate.getWarType() == 0).map(TWarReceive::getWarFee).reduce(BigDecimal.ZERO, BigDecimal::add);
        /**领取金币*/
        if(addBalance.compareTo(BigDecimal.ZERO) > 0){
            BigDecimal beforeBalance = tUser.getUserBalance();
            tUser.setUserBalance(beforeBalance.add(addBalance));
            tUser.setUpdateTime(DateUtils.getNowDate());
            int row1 = tUserMapper.updateTUserBalance(tUser);
            if(row1 == 0){
                throw new SQLException("网络延迟,请重新抽奖! ");
            }

            /**余额变更记录表*/
            TBalanceChange balanceChange = new TBalanceChange();
            balanceChange.setUserId(userId);
            balanceChange.setBalanceBefore(beforeBalance);
            balanceChange.setBalanceAfter(tUser.getUserBalance());
            balanceChange.setOperationType(Constants.OPERATIONTYPE17);
            balanceChange.setFrequency(1);
            balanceChange.setFee(addBalance);
            balanceChange.setCorrespondingid(warId);
            balanceChange.setCreateTime(DateUtils.getNowDate());
            balanceChange.setSecondCurrencyAfter(tUser.getSecondCurrency());
            balanceChange.setSecondCurrencyBefore(tUser.getSecondCurrency());
            balanceChange.setProfitPrice(addBalance);
            tBalanceChangeMapper.insertTBalanceChange(balanceChange);
        }
        return Response.success("领取成功");
    }

    /**
     * @Desc: 计算战令消费
     * @author: zz
     * @date: 2023/12/13
     */
    @Override
    public void computeWarFlow(String userId, BigDecimal consumeValue){
        TWar tWar = tWarMapper.lastWar();
        Long currentTime = DateUtils.getNowDate().getTime();
        /**战令未开启不进行计算*/
        if(tWar == null || tWar.getBeginTime().getTime() > currentTime || tWar.getCloseTime().getTime() < currentTime){
            return;
        }
        TWarUser tWarUser = tWarUserMapper.getWarUser(tWar.getObjectId(),userId);
        if(tWarUser == null){
            int complateGrate = tWarGrateMapper.getMaxGrateByExperience(tWar.getObjectId(),consumeValue);
            tWarUser = new TWarUser();
            tWarUser.setWarGrate(complateGrate);
            tWarUser.setUserId(userId);
            tWarUser.setWarId(tWar.getObjectId());
            tWarUser.setDraftValue(consumeValue);
            tWarUser.setCreateTime(DateUtils.getNowDate());
            tWarUserMapper.insertTWarUser(tWarUser);
        }else {
            tWarUserMapper.updateWarGrateAndValue(tWarUser.getId(),consumeValue);
        }
    }

//    /**
//     * @Desc: 计算战令充值流水
//     * @author: zz
//     * @date: 2023/12/13
//     */
//    @Override
//    public void computeCzWarFlow(String userId, BigDecimal czMoney){
//        TWar tWar = tWarMapper.lastWar();
//        Long currentTime = DateUtils.getNowDate().getTime();
//        /**战令未开启不进行计算*/
//        if(tWar == null || tWar.getBeginTime().getTime() > currentTime || tWar.getCloseTime().getTime() < currentTime){
//            return;
//        }
//        BigDecimal flowfee = BigDecimal.ZERO;
//        if(StringUtils.isEmpty(tWar.getWeeklyLimit())){/**未设置周上限*/
//            flowfee = flowfee.add(czMoney);
//        }else {
//            /**设置了周经验上限*/
//            JSONObject jsonObject = JSON.parseObject(tWar.getWeeklyLimit());
//            Long currentWeek = this.getCurrentWeek(tWar.getBeginTime(),tWar.getCloseTime());
//            Object sx = jsonObject.get(currentWeek);
//            if(Objects.isNull(sx)){
//                flowfee = flowfee.add(czMoney);
//            }else {
//                String startTime = getStartOfCurrentWeek(tWar.getBeginTime());
//                /**当前时间段的总充值,包括此处充值*/
//                BigDecimal curryWeekValue = tRechargeMapper.userCzMoneyRange(userId,startTime,DateUtils.dateTimeNow());
//
//                BigDecimal sxValue = new BigDecimal(jsonObject.get(currentWeek).toString());
//                if(curryWeekValue.compareTo(sxValue)<= 0){
//                    flowfee = flowfee.add(czMoney);
//                }else {
//                    BigDecimal ad = czMoney.subtract(curryWeekValue.subtract(sxValue));
//                    flowfee = ad.compareTo(BigDecimal.ZERO)>0 ? ad : BigDecimal.ZERO;
//                }
//            }
//        }
//        /**存在经验变动才计算后面的*/
//        if(flowfee.compareTo(BigDecimal.ZERO)>0){
//            TWarUser tWarUser = tWarUserMapper.getWarUser(tWar.getObjectId(),userId);
//            BigDecimal totalDraftValue = flowfee.add(tWarUser == null ? BigDecimal.ZERO : tWarUser.getDraftValue());
//            int complateGrate = tWarGrateMapper.getMaxGrateByExperience(tWar.getObjectId(),totalDraftValue);
//            if(tWarUser == null){
//                tWarUser = new TWarUser();
//                tWarUser.setWarGrate(complateGrate);
//                tWarUser.setUserId(userId);
//                tWarUser.setWarId(tWar.getObjectId());
//                tWarUser.setDraftValue(totalDraftValue);
//                tWarUser.setCreateTime(DateUtils.getNowDate());
//                tWarUserMapper.insertTWarUser(tWarUser);
//            }else {
//                tWarUser.setDraftValue(totalDraftValue);
//                if(tWarUser.getWarGrate() < complateGrate){
//                    /**等级升级*/
//                    tWarUser.setWarGrate(complateGrate);
//                }
//                int row = tWarUserMapper.updateTWarUser(tWarUser);
//                if(row == 0){
//                    throw new CustomException("网络延迟,请重新抽奖! ");
//                }
//            }
//        }
//    }

    /**
     * @Desc: 计算当前日期属于第几周
     * @author: zz
     * @date: 2023/12/13
     */
    public Long getCurrentWeek(Date beginTime, Date closeTime){
        LocalDate startDate = beginTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate endDate = closeTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

        endDate = endDate.plusDays(1);
        long weeks = ChronoUnit.WEEKS.between(startDate, endDate);
        long remainingDays = ChronoUnit.DAYS.between(startDate, endDate) % 7;
        weeks = remainingDays>0 ? weeks+1 : weeks;
        return weeks;
    }
    /**
     * @Desc: 计算当前周的开始计算时间
     * @author: zz
     * @date: 2023/12/13
     */
    public String getStartOfCurrentWeek(Date beginTime){
        LocalDate startDate = beginTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

        LocalDate currentDate = LocalDate.now();
        long currentWeek = ChronoUnit.WEEKS.between(startDate, currentDate);
        LocalDate startOfCurrentWeek = startDate.plusWeeks(currentWeek);

//        LocalDate endOfCurrentWeek = startOfCurrentWeek.plusDays(6);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return startOfCurrentWeek.format(formatter) + " 00:00:00";
    }

}
